<?php

namespace App\Http\Middleware;

use Closure;
use Exception;
use StdClass;
use App\Ext\RedisCache;
use App\Ext\Wechat\Common;
use App\Model\WechatMp;

class Wechat
{
    /**
     * Handle an incoming request.
     *
     * @param \Illuminate\Http\Request  $request
     * @param Closure $next
     * @return mixed
     * @throws Exception
     */
    public function handle($request, Closure $next)
    {
        if ($request->has('state')) {
            $id = $request->input('state');
            $request->wechat =  new StdClass();
            // 公众号配置
            $request->wechat->config = $this->getConfig($id);
            if ($request->wechat->config == false) {
                throw new Exception('Config is not defined!');
            }
            // 公共号身份码token
            $appID = $request->wechat->config['app_id'];
            $appSecret = $request->wechat->config['app_secret'];
            $request->wechat->token = $this->getToken($id, $appID, $appSecret);
            if ($request->wechat->token == false) {
                throw new Exception('Token is not defined!');
            }
            // 微信支付安全证书
            $request->wechat->cert = $this->cert();
            return $next($request);
        }
        throw new Exception('mp_id is not defined!');
    }

    private function getConfig($id)
    {
        $key = 'wechat:config:' . $id;
        $redisCache = new RedisCache();
        if ($redisCache->check($key)) {
            return $redisCache->getHash($key);
        } else {
            $result = WechatMp::find($id);
            if ($result) {
                $param  = [
                    'id' => $id,
                    'app_id' => $result->app_id,
                    'app_secret' => $result->app_secret,
                    'token' => $result->token,
                    'encoding_aes_key' => $result->encoding_aes_key,
                    'mch_id' => $result->mch_id,
                    'api_key' => $result->api_key,
                ];
                $redisCache->setHash($key, $param);
                return $param;
            }
        }
        return false;
    }

    private function getToken($id, $appID, $appSecret)
    {
        $key = 'wechat:token:' . $id;
        $redisCache = new RedisCache();
        if ($redisCache->check($key)) {
            return $redisCache->get($key);
        } else {
            $token = Common::accessToken($appID, $appSecret);
            if ($token && !empty($token->access_token)) {
                $redisCache->set($key, $token->access_token, $token->expires_in - 300);
                return $token->access_token;
            }
        }
        return false;
    }

    private function cert()
    {
        $certPath = path('app', 'Cert');
        $cert = [
            'cert' => $certPath . 'apiclient_cert.pem',
            'key' => $certPath . 'apiclient_key.pem'
        ];
        return $cert;
    }

}
